package com.yin.bank.biz;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yin.bank.entity.Account;
import com.yin.bank.entity.Oprecord;
import com.yin.bank.mapper.AccountMapper;
import com.yin.bank.mapper.OprecordMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.DefaultTransactionDefinition;

import javax.sql.DataSource;
import java.time.LocalDateTime;
import java.util.List;

@Service
@Transactional(rollbackFor = BizException.class)
public class BankBiz {

    @Autowired
    private AccountMapper accountMapper;
    @Autowired
    private OprecordMapper oprecordMapper;

    @Autowired
    private DataSource dataSource;

    // 存款(deposit), 取款(withdraw), 转账(transfer), 开户(register), 查询(query)
    public void deposit(Long aid, Double money, String depositRemark) throws BizException {
//        // 1. 校验参数
//        if (aid == null || money == null) {
//            throw new IllegalArgumentException("参数错误");
//        }
//        // 2. 调用mapper
//        accountMapper.updateById(aid, money);
        // 开启事务
        PlatformTransactionManager transactionManager = new DataSourceTransactionManager(dataSource);
        // 定义事物属性
        TransactionDefinition transactionDefinition = new DefaultTransactionDefinition();
        // 获取事务状态
        TransactionStatus status = transactionManager.getTransaction(transactionDefinition);

        try {
            // 1. 查询账户
            Account account = accountMapper.selectById(aid);
            if (account == null) {
                throw new BizException("账户不存在");
            }
            // 2. 存款
            account.setBalance(account.getBalance() + money);
            // 3. 更新账户
            accountMapper.updateById(account);
            Oprecord oprecord = new Oprecord();
            oprecord.setAid(aid);
            oprecord.setOpmoney(money);
            oprecord.setOptime(LocalDateTime.now());
            oprecord.setRemark(depositRemark);

//            int i = 1 / 0;
            // 4. 记录操作日志
            oprecordMapper.insert(oprecord);

            // 提交事务
            transactionManager.commit(status);
        } catch (Exception e) {
            // 回滚事务
            transactionManager.rollback(status);
            throw e;
        }
    }

    @Transactional(rollbackFor = BizException.class)
    public void withdraw(Long aid, Double money, String withdrawRemark) throws BizException {
        // 1. 查询账户
        Account account = accountMapper.selectById(aid);
        // 1.1 校验账户是否存在
        if (account == null) {
            throw new BizException("账户不存在");
        }
        // 1.2 校验账户余额是否充足
        if (account.getBalance() < money) {
            throw new BizException("账户余额不足");
        }
        // 2. 取款
        account.setBalance(account.getBalance() - money);
        // 3. 更新账户
        accountMapper.updateById(account);
        // 4. 记录操作日志
        Oprecord oprecord = new Oprecord();
        oprecord.setAid(aid);
        oprecord.setOpmoney(money);
        oprecord.setOptime(LocalDateTime.now());

        oprecord.setRemark(withdrawRemark);

        if (money == 7000) {
            throw new BizException(withdrawRemark + "失败");
        }


        // 5. 记录操作日志
        oprecordMapper.insert(oprecord);
    }

    public void transfer(Long fromAid, Long toAid, Double money, String transferRemark) throws BizException {
        withdraw(fromAid, money, transferRemark);
        deposit(toAid, money, transferRemark);

    }

    public void register(Long aid, Double money) throws BizException {
        accountMapper.insert(new Account("123456", money));
        if (aid == 3000000000L) {
            throw new BizException("开户失败");
        }

    }

    public List<Oprecord> query(Long aid) {
        LambdaQueryWrapper<Oprecord> eq = new LambdaQueryWrapper<>();
        eq.eq(Oprecord::getAid, aid);
        return oprecordMapper.selectList(eq);
    }

    public Page<Oprecord> queryByPage(Long aid, int current, int size) {
        LambdaQueryWrapper<Oprecord> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Oprecord::getAid, aid);
        Page<Oprecord> page = new Page<>(current, size);
        return oprecordMapper.selectPage(page, queryWrapper);
    }

    public Account login(String id, String password) throws BizException {
        LambdaQueryWrapper<Account> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Account::getId, id);
        queryWrapper.eq(Account::getPassword, password);
        Account account = accountMapper.selectOne(queryWrapper);
        if (account == null) {
            throw new BizException("登录失败");
        }
        account.setPassword(null);
        return account;
    }
}
